<template>
  <div class="resource-container">
    <!-- 搜索区域 -->
    <a-card class="search-card" :bordered="false">
      <a-form :model="searchForm" class="search-form">
        <div class="search-row">
          <a-form-item label="应用" class="search-item">
            <a-select
              v-model:value="searchForm.applicationCode"
              placeholder="请选择应用"
              allowClear
              @change="handleApplicationChange"
            >
              <a-select-option
                v-for="application in applicationList"
                :key="application.applicationCode"
                :value="application.applicationCode"
              >
                {{ application.name }}
              </a-select-option>
            </a-select>
          </a-form-item>
          <a-form-item label="" class="search-item search-buttons">
            <a-space>
              <a-button type="primary" @click="handleSearch">
                <template #icon><search-outlined /></template>
                查询
              </a-button>
              <a-button @click="handleReset">
                <template #icon><reload-outlined /></template>
                重置
              </a-button>
            </a-space>
          </a-form-item>
        </div>
      </a-form>
    </a-card>

    <!-- 资源列表和详情 -->
    <a-row :gutter="16" class="content-row">
      <a-col :span="14">
        <!-- 资源列表卡片 -->
        <a-card class="resource-card" :bordered="false">
          <template #title>
            <div class="card-title">
              <a-button
                type="primary"
                @click="handleUploadAll"
                :loading="uploading"
              >
                <template #icon><upload-outlined /></template>
                上传全量权限
              </a-button>
              <a-space>
                <a-button @click="handleExpandAll">
                  <template #icon><fullscreen-outlined /></template>
                  展开全部
                </a-button>
                <a-button @click="handleCollapseAll">
                  <template #icon><fullscreen-exit-outlined /></template>
                  收起全部
                </a-button>
              </a-space>
            </div>
          </template>

          <div class="tree-container">
            <a-spin :spinning="loading">
              <a-empty
                v-if="resourceTree.length === 0"
                description="暂无资源数据"
              />
              <a-tree
                v-else
                :tree-data="resourceTree"
                :field-names="{
                  children: 'children',
                  title: 'title',
                  key: 'key',
                }"
                show-line
                :blockNode="true"
                :selectable="true"
                :selectedKeys="selectedKeys"
                :auto-expand-parent="true"
                :expanded-keys="expandedKeys"
                @expand="onExpand"
                @select="onSelect"
              >

                <template #title="{ node, data }">
                  <div class="tree-node" @click="handleNodeClick(data)">
                    <div class="node-title">
                      <div
                        class="node-icon"
                        :class="{
                          'node-icon-directory': data.type === 'DIRECTORY',
                          'node-icon-menu': data.type === 'MENU',
                          'node-icon-button': data.type === 'BUTTON',
                          'node-icon-api': data.type === 'API'
                        }"
                      >
                        <folder-open-outlined v-if="data.type === 'DIRECTORY'" />
                        <menu-outlined v-else-if="data.type === 'MENU'" />
                        <control-outlined v-else-if="data.type === 'BUTTON'" />
                        <api-outlined v-else-if="data.type === 'API'" />
                      </div>
                      <div class="node-text">
                        {{ data.name }}
                        <a-tag
                          v-if="data.type"
                          :color="getTypeColor(data.type)"
                          size="small"
                        >
                          {{ getTypeLabel(data.type) }}
                        </a-tag>
                        <a-tag
                          v-if="data.type === 'API' && data.method"
                          color="blue"
                          size="small"
                        >
                          {{ data.method }}
                        </a-tag>
                      </div>
                    </div>
                  </div>
                </template>
              </a-tree>
            </a-spin>
          </div>
        </a-card>
      </a-col>
      <a-col :span="10">
        <!-- 资源详情卡片 -->
        <a-card class="detail-card" title="资源详情" :bordered="false">
          <a-empty
            v-if="!selectedNode || !selectedNode.name"
            description="请选择一个资源"
          />
          <div v-else class="resource-detail">
            <a-descriptions :column="1" size="small" bordered>
              <a-descriptions-item label="资源名称">
                {{ selectedNode.name }}
              </a-descriptions-item>
              <a-descriptions-item label="资源类型">
                <a-tag :color="getTypeColor(selectedNode.type)">
                  {{ getTypeLabel(selectedNode.type) }}
                </a-tag>
              </a-descriptions-item>
              <a-descriptions-item label="资源编码">
                {{ selectedNode.code || selectedNode.code }}
              </a-descriptions-item>
              <a-descriptions-item
                v-if="selectedNode.parent_code"
                label="父级编码"
              >
                {{ selectedNode.parent_code }}
              </a-descriptions-item>
              <a-descriptions-item v-if="selectedNode.path" label="路径">
                {{ selectedNode.path }}
              </a-descriptions-item>
              <a-descriptions-item v-if="selectedNode.method" label="请求方法">
                <a-tag color="blue">{{ selectedNode.method }}</a-tag>
              </a-descriptions-item>
              <a-descriptions-item
                v-if="selectedNode.component"
                label="组件路径"
              >
                {{ selectedNode.component }}
              </a-descriptions-item>
            </a-descriptions>
          </div>
        </a-card>
      </a-col>
    </a-row>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted } from "vue";
import { message, Modal } from "ant-design-vue";
import {
  SearchOutlined,
  ReloadOutlined,
  UploadOutlined,
  FullscreenOutlined,
  FullscreenExitOutlined,
  FolderOpenOutlined,
  MenuOutlined,
  ControlOutlined,
  ApiOutlined,
} from "@ant-design/icons-vue";
import { getResourceTree, uploadResourceTree } from "@/api/resource";

import { getApplicationList } from "@/api/application";
import { RESOURCE_TREE } from "@/constants/resourceTree";
import { APPLICATION_CODE } from "@/constants/constants";

// 响应式数据
const loading = ref(false);
const uploading = ref(false);
const applicationList = ref([]);
const resourceTree = ref([]);
const expandedKeys = ref([]);
const selectedKeys = ref([]);
const selectedNode = ref(null);
const searchForm = reactive({
  applicationId: APPLICATION_CODE,
});

// 资源类型配置
const RESOURCE_TYPE = {
  DIRECTORY: { label: "目录", color: "blue" },
  MENU: { label: "菜单", color: "green" },
  BUTTON: { label: "按钮", color: "orange" },
  API: { label: "接口", color: "purple" },
};

// 资源类型配置已在上方定义

// 获取类型标签
const getTypeLabel = (type) => {
  return RESOURCE_TYPE[type]?.label || "未知";
};

// 获取类型颜色
const getTypeColor = (type) => {
  return RESOURCE_TYPE[type]?.color || "default";
};

// 生命周期钩子
onMounted(() => {
  fetchApplicationList();
});

// 获取应用列表
const fetchApplicationList = async () => {
  try {
    const param = {
      pageNum: 1,
      pageSize: 1000,
    };
    const res = await getApplicationList(param);
    applicationList.value = res.data.items || [];
  } catch (error) {
    message.error("获取应用列表失败");
  }
};

// 获取资源树
const fetchResourceTree = async () => {
  loading.value = true;
  expandedKeys.value = []; // 重置展开的节点

  try {
    const res = await getResourceTree(APPLICATION_CODE);
    const treeData = res.data || [];
    resourceTree.value = convertToTreeData(treeData);

    // 默认展开第一级节点
    if (resourceTree.value.length > 0) {
      const firstLevelKeys = resourceTree.value.map((item) => item.key);
      expandedKeys.value = firstLevelKeys;
    }
  } catch (error) {
    message.error("获取资源树失败");
    resourceTree.value = [];
  } finally {
    loading.value = false;
  }
};

// 将后端返回的资源树转换为前端树组件需要的格式
const convertToTreeData = (data) => {
  return data.map((item) => {
    const node = {
      key: item.id.toString(),
      id: item.id,
      name: item.name,
      code: item.code,
      parentCode: item.parentCode,
      type: item.type,
      path: item.path,
      method: item.method,
      title: item.name,
      component: item.component,
    };

    if (item.children && item.children.length > 0) {
      node.children = convertToTreeData(item.children);
    }

    return node;
  });
};

// 应用变更处理
const handleApplicationChange = () => {
  fetchResourceTree();
};

// 搜索
const handleSearch = () => {
  fetchResourceTree();
};

// 重置搜索条件
const handleReset = () => {
  Object.assign(searchForm, {
    applicationCode: undefined,
  });
  resourceTree.value = [];
};

// 展开/收起节点
const onExpand = (keys, info) => {
  const expanded = info.expanded;
  const node = info.node;
  
  if (!expanded) {
    // 如果是收起操作，需要同时收起所有子节点
    const removeChildKeys = (nodeData) => {
      if (!nodeData.children) return [];
      
      let childKeys = [];
      const traverse = (children) => {
        if (!children) return;
        
        children.forEach(child => {
          childKeys.push(child.key);
          if (child.children) {
            traverse(child.children);
          }
        });
      };
      
      traverse(nodeData.children);
      return childKeys;
    };
    
    // 获取当前节点的所有子节点的key
    const childKeys = removeChildKeys(node.dataRef);
    
    // 从expandedKeys中移除所有子节点的key
    expandedKeys.value = keys.filter(key => !childKeys.includes(key));
  } else {
    // 如果是展开操作，直接使用传入的keys
    expandedKeys.value = keys;
  }
};

// 选择节点
const onSelect = (keys, info) => {
  selectedKeys.value = keys;
  // 无论keys是否为空，只要有选中的节点信息就设置selectedNode
  selectedNode.value = info.node;
};

// 节点点击处理
const handleNodeClick = (data) => {
  selectedNode.value = data;
  selectedKeys.value = [data.key];
};

// 展开全部节点
const handleExpandAll = () => {
  const allKeys = [];
  const flatten = (nodes) => {
    if (!nodes || !nodes.length) return;
    nodes.forEach((node) => {
      allKeys.push(node.key);
      if (node.children && node.children.length) {
        flatten(node.children);
      }
    });
  };
  flatten(resourceTree.value);
  expandedKeys.value = allKeys;
};

// 收起全部节点
const handleCollapseAll = () => {
  expandedKeys.value = [];
};

// 上传全量权限
const handleUploadAll = async () => {
  Modal.confirm({
    title: "确认上传",
    content: "上传将覆盖当前应用的资源树，确定要继续吗？",
    okText: "确定",
    cancelText: "取消",
    async onOk() {
      uploading.value = true;
      try {
        // 调用后端API上传资源树
        await uploadResourceTree(APPLICATION_CODE, RESOURCE_TREE);
        message.success("资源树上传成功");
      } catch (error) {
        console.error("上传资源树失败:", error);
        message.error("上传资源树失败: " + (error.message || "未知错误"));
      } finally {
        uploading.value = false;
      }
    },
  });
};

// 将树形结构转换为平铺结构
const flattenTree = (treeData, parentId = 0) => {
  let result = [];

  treeData.forEach((node) => {
    // 创建一个新对象，不包含UI相关的属性
    const resourceNode = {
      parentId: parentId,
      name: node.name,
      code: node.code,
      type: node.type,
      sort: node.sort || 0,
    };

    // 根据资源类型添加特定属性
    if (node.type === "MENU") {
      resourceNode.path = node.path;
    } else if (node.type === "API") {
      resourceNode.path = node.path;
      resourceNode.method = node.method;
    }

    result.push(resourceNode);

    // 递归处理子节点
    if (node.children && node.children.length > 0) {
      // 使用当前节点的ID作为子节点的父ID
      const childrenNodes = flattenTree(node.children, node.id);
      result = result.concat(childrenNodes);
    }
  });

  return result;
};
</script>

<style lang="scss" scoped>
.resource-container {
  padding: 20px;
  background-color: #f5f7fa;

  .search-card {
    margin-bottom: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);

    :deep(.ant-card-body) {
      padding: 20px;
    }

    .search-form {
      .search-row {
        display: flex;
        gap: 20px;
        margin-bottom: 16px;

        .search-item {
          flex: 0 0 calc(33.333% - 14px);
          margin-bottom: 0;

          :deep(.ant-form-item-label) {
            width: 80px;
            text-align: right;
          }

          :deep(.ant-form-item-control) {
            flex: 1;
          }
        }
      }

      .search-buttons {
        display: flex;
        justify-content: flex-start;
        margin-bottom: 16px;
      }
    }
  }

  .content-row {
    margin-bottom: 20px;
  }

  .resource-card {
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    transition: all 0.3s;

    :deep(.ant-card-head) {
      min-height: 56px;
      padding: 0 20px;
      background-color: #fafafa;
      border-bottom: 1px solid #f0f0f0;
      border-radius: 8px 8px 0 0;

      .ant-card-head-title {
        padding: 16px 0;
        font-size: 16px;
        font-weight: 600;
      }
    }

    :deep(.ant-card-body) {
      padding: 20px;
    }

    .card-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
    }

    .tree-container {
      height: calc(100vh - 250px);
      border: 1px solid #f0f0f0;
      padding: 16px;
      border-radius: 8px;
      background-color: #fafafa;
      overflow: auto;

      :deep(.ant-tree) {
        .ant-tree-treenode {
          padding: 0;
          transition: background-color 0.3s;
          border-radius: 6px;
          margin: 1px 0;
          height: 24px;
          line-height: 24px;
          display: flex;
          align-items: center;

          &:hover {
            background-color: #f0f7ff;
          }

          &.ant-tree-treenode-selected {
            background-color: #1890ff !important;

            .ant-tree-node-content-wrapper {
              color: white !important;
            }

            .tree-node {
              .node-title {
                .node-icon {
                  color: white !important;
                }

                .node-text {
                  color: white !important;

                  .ant-tag {
                    background-color: rgba(255, 255, 255, 0.2) !important;
                    color: white !important;
                    border-color: rgba(255, 255, 255, 0.3) !important;
                  }
                }
              }
            }
          }
        }
        
        .ant-tree-checkbox {
          margin-right: 8px;
          vertical-align: middle;
          margin-top: 0;
        }

        .ant-tree-node-content-wrapper {
          transition: background-color 0.3s;
          padding: 0 2px;
          display: inline-flex;
          align-items: center;
          vertical-align: middle;

          &:hover {
            background-color: transparent;
          }

          &.ant-tree-node-selected {
            background-color: transparent;
          }
        }

        .ant-tree-switcher {
          transition: all 0.3s;
          line-height: 1;
          width: 20px;
          height: 24px;
          display: flex;
          align-items: center;
          justify-content: center;
          vertical-align: middle;
          margin-top: 0;
          padding-right: 0;

          &:hover {
            background-color: #e6f7ff;
            border-radius: 4px;
          }

          .ant-tree-switcher-icon {
            font-size: 12px;
            color: #1890ff;
            display: flex;
            align-items: center;
            justify-content: center;
          }
        }

        .ant-tree-indent-unit {
          width: 16px;
          height: 24px;
          line-height: 24px;
          vertical-align: middle;
        }
      }

      .tree-node {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        padding: 0;
        cursor: pointer;
        transition: all 0.2s;
        height: 24px;
        line-height: 24px;

        &:hover {
          transform: translateX(2px);
        }

        .node-title {
          display: flex;
          align-items: center;

          .node-icon {
            margin-right: 4px;
            font-size: 16px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            width: 20px;
            height: 24px;
            border-radius: 4px;
            transition: all 0.3s;
            vertical-align: middle;

            &-directory {
              color: #1890ff;
            }

            &-menu {
              color: #52c41a;
            }

            &-button {
              color: #fa8c16;
            }

            &-api {
              color: #722ed1;
            }
          }

          .node-text {
            display: inline-flex;
            align-items: center;
            gap: 4px;
            font-weight: 500;
            font-size: 14px;
            vertical-align: middle;

            .ant-tag {
              font-size: 11px;
              line-height: 16px;
              height: 18px;
              padding: 0 4px;
              margin-right: 0;
              border-radius: 10px;
            }
          }
        }
      }
    }
  }

  .detail-card {
    height: calc(100vh - 250px);
    overflow: auto;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
    transition: all 0.3s;

    :deep(.ant-card-head) {
      min-height: 56px;
      padding: 0 20px;
      background-color: #fafafa;
      border-bottom: 1px solid #f0f0f0;
      border-radius: 8px 8px 0 0;

      .ant-card-head-title {
        padding: 16px 0;
        font-size: 16px;
        font-weight: 600;
        color: #1890ff;
      }
    }

    :deep(.ant-card-body) {
      padding: 20px;
    }

    .resource-detail {
      padding: 0;

      :deep(.ant-descriptions) {
        .ant-descriptions-item-label {
          width: 90px;
          background-color: #fafafa;
          font-weight: 500;
        }

        .ant-descriptions-item-content {
          word-break: break-all;
          padding: 12px 16px;
        }

        .ant-tag {
          margin-right: 0;
          border-radius: 10px;
        }
      }
    }
  }

  .action-btns {
    display: flex;
    gap: 6px;
    justify-content: center;
  }
}
</style>
